package com.socialin.android.hackaton.draw.drawing;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.Log;

public class ShapeDrawer1 {
	
	public final static int SHAPE_TYPE_FOCAL = 0;
	public final static int SHAPE_TYPE_RECTANGLE = 1;
	
	private final static float TOUCH_MOVE_TOLERANCE = 2f;
	private final static float CIRCLE_HANDE_TOUCH_MOVE_TOLERANCE = 2f;
	
	private int shapeType = SHAPE_TYPE_RECTANGLE;


	private  float shapeSizeHandeRadius = 25f;
	private  float shapeScaleHandeRadius = 25f;

	private final static float RADIUS_MIN_SIZE = 30f;

	Shape shape = null;

	private Paint strokePaint = null;
	private Paint handePaint = null;

	private boolean circleTouched = false;
	private boolean circleHandeTouched = false;
	private float oldTouchX = 0;
	private float oldTouchY = 0;
	
	private Bitmap shapeSizeHandle = null;
	private Bitmap shapeScaleHandeBitmap = null;


	public class Shape {
		
		private final static int LEFT_SCALE_HANDE = 0;
		private final static int RIGHT_SCALE_HANDE = 1;
		private final static int TOP_SCALE_HANDE = 2;
		private final static int BOTTOM_SCALE_HANDE = 3;
		private int touchedHande = -1;
		
		PointF centerXY = null;
		float radius = 0;
		PointF handeXY = null;
		float scaleX = 1f;
		float scaleY = 1f;

		public Shape() {

		}

		public Shape(PointF centerXY, float radius) {
			this.centerXY = centerXY;
			this.radius = radius;
			handeXY = new PointF();
			setHandeXY();
		}

		public void setCenterXY(float centerX, float centerY) {
			centerXY.x = centerX;
			centerXY.y = centerY;
			setHandeXY();
		}

		public void setRadius(float newRadius) {
			this.radius = newRadius;
			setHandeXY();
		}
		
		
		public Rect getDrawRect()
		{
			int rectLeft = (int)(centerXY.x -radius*scaleX);
			int rectTop = (int) (centerXY.y-radius*scaleY);
			int rectRight = (int)(centerXY.x +radius*scaleX);
			int rectBottom = (int)(centerXY.y+radius*scaleY);
			if(rectLeft>rectRight)
			{
				int s = rectLeft;
				rectLeft = rectRight;
				rectRight = s;
			}
			if(rectTop>rectBottom)
			{
				int s = rectTop;
				rectTop = rectBottom;
				rectBottom = s;
			}
			return new Rect(rectLeft,rectTop, rectRight,rectBottom);
		}

		private void setHandeXY() {

			switch (shapeType) {
			case SHAPE_TYPE_FOCAL:
				handeXY.x = (float)(centerXY.x+Math.abs(Math.cos(Math.toRadians(-45))*radius*scaleX)+shapeSizeHandeRadius+10f);
				handeXY.y = (float)(centerXY.y+Math.abs(Math.sin(Math.toRadians(-45))*radius*scaleY)+shapeSizeHandeRadius+10f);
				break;

			case SHAPE_TYPE_RECTANGLE:
				handeXY.x = (float)(centerXY.x+radius*Math.abs(scaleX)+shapeSizeHandeRadius+10f);
				handeXY.y = (float)(centerXY.y+radius*Math.abs(scaleY)+shapeSizeHandeRadius+10f);
				break;
			}
		}
		public void drawShape(Canvas canvas)
		{
			strokePaint.setStrokeWidth(2f/(float)(Math.sqrt(Math.pow(scaleX, 2)+Math.pow(scaleY,2))));
			strokePaint.setColor(0xffde7108);
			canvas.save();
			canvas.scale(scaleX, scaleY);
			switch (shapeType) {
			case SHAPE_TYPE_FOCAL:
				canvas.drawCircle(centerXY.x/scaleX, centerXY.y/scaleY, radius, strokePaint);
				break;

			case SHAPE_TYPE_RECTANGLE:
				canvas.drawRect(centerXY.x/scaleX-radius, centerXY.y/scaleY-radius, centerXY.x/scaleX+radius, centerXY.y/scaleY+radius, strokePaint);
				break;
			}
			canvas.restore();
			canvas.drawBitmap(shapeSizeHandle, handeXY.x - shapeSizeHandle.getWidth() / 2, handeXY.y - shapeSizeHandle.getHeight() / 2, handePaint);
			
			canvas.drawBitmap(shapeScaleHandeBitmap, (centerXY.x - shapeScaleHandeRadius-radius*scaleX), centerXY.y-shapeScaleHandeRadius, handePaint);
			canvas.drawBitmap(shapeScaleHandeBitmap, (centerXY.x - shapeScaleHandeRadius+radius*scaleX), centerXY.y-shapeScaleHandeRadius, handePaint);
			canvas.drawBitmap(shapeScaleHandeBitmap, (centerXY.x - shapeScaleHandeRadius), (centerXY.y-shapeScaleHandeRadius-radius*scaleY), handePaint);
			canvas.drawBitmap(shapeScaleHandeBitmap, (centerXY.x - shapeScaleHandeRadius), (centerXY.y-shapeScaleHandeRadius+radius*scaleY), handePaint);
		}
		public float getScaledHorizontalRadius()
		{
			return Math.abs(radius*scaleX);
		}
		public float getScaledVerticalRadius()
		{
			return Math.abs(radius*scaleY);
		}
		
		public boolean handeTouched(float x,float y)
		{
			if(isTouchedInHande(centerXY.x -radius*scaleX, centerXY.y, x, y))
			{
				touchedHande = LEFT_SCALE_HANDE;
				return true;
			}
			if(isTouchedInHande(centerXY.x +radius*scaleX, centerXY.y, x, y))
			{
				touchedHande = RIGHT_SCALE_HANDE;
				return true;
			}
			if(isTouchedInHande(centerXY.x, centerXY.y-radius*scaleY, x, y))
			{
				touchedHande = TOP_SCALE_HANDE;
				return true;
			}
			if(isTouchedInHande(centerXY.x, centerXY.y+radius*scaleY, x, y))
			{
				touchedHande = BOTTOM_SCALE_HANDE;
				return true;
			}
			return false;
		}
		
		public boolean moveHandeCircle(float dx,float dy)
		{
			switch (touchedHande) {
			case LEFT_SCALE_HANDE:
				if(Math.abs(dx)>=CIRCLE_HANDE_TOUCH_MOVE_TOLERANCE)
				{
					scaleX = (scaleX*radius-dx)/radius;
					return true;
				}
				break;
			case RIGHT_SCALE_HANDE:

				if(Math.abs(dx)>=CIRCLE_HANDE_TOUCH_MOVE_TOLERANCE)
				{
					scaleX = (scaleX*radius+dx)/radius;
					return true;
				}
				break;
			case TOP_SCALE_HANDE:
				if(Math.abs(dy)>=CIRCLE_HANDE_TOUCH_MOVE_TOLERANCE)
				{
					scaleY = (scaleY*radius-dy)/radius;
					return true;
				}
				break;
			case BOTTOM_SCALE_HANDE:
				if(Math.abs(dy)>=CIRCLE_HANDE_TOUCH_MOVE_TOLERANCE)
				{
					scaleY = (scaleY*radius+dy)/radius;
					return true;
				}
				break;
			}
			return false;
		}
		
		private boolean isTouchedInHande(float handeCenterX,float handeCenterY,float x,float y)
		{
			if(x>=handeCenterX-shapeScaleHandeRadius && x<=handeCenterX+shapeScaleHandeRadius &&
					y>=handeCenterY-shapeScaleHandeRadius && y<=handeCenterY+shapeScaleHandeRadius)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		public  boolean isPointInShape(float x,float y)
		{
			switch (shapeType) {
			case SHAPE_TYPE_FOCAL:
				if(Math.pow((centerXY.x-x), 2)*Math.pow(radius*scaleY, 2)+Math.pow((centerXY.y-y), 2)*Math.pow(radius*scaleX, 2)<=Math.pow(radius*radius*scaleX*scaleY,2))
				{
					return true;
				}
				break;

			case SHAPE_TYPE_RECTANGLE:
				if(x>=centerXY.x-radius*Math.abs(scaleX) && x<=centerXY.x+radius*Math.abs(scaleX) && 
					y>=centerXY.y-radius*Math.abs(scaleY) && y<=centerXY.y+radius*Math.abs(scaleY))
				{
					return true;
				}
				break;
			}
			
			return false;
		}
	}
	
	public void setShapeType(int shapeType)
	{
		this.shapeType = shapeType;
	}

	public ShapeDrawer1(Bitmap shapeSizeHandleBm,Bitmap shapeScaleHandeBitmap) {
		strokePaint = new Paint();
		strokePaint.setAntiAlias(true);
		strokePaint.setStyle(Paint.Style.STROKE);

		handePaint = new Paint();
		handePaint.setAntiAlias(true);

		this.shapeSizeHandle = shapeSizeHandleBm;
		this.shapeScaleHandeBitmap = shapeScaleHandeBitmap;
		
		shapeSizeHandeRadius = Math.max((shapeSizeHandle.getWidth() / 2f), shapeSizeHandle.getHeight() / 2f);
		shapeScaleHandeRadius = Math.max(shapeScaleHandeBitmap.getWidth()/2f, shapeScaleHandeBitmap.getHeight()/2f);
	}

	public void setCircle(float bitmapWidth, float bitmapHeight) {
		PointF centerXY = new PointF(bitmapWidth / 2f , bitmapHeight / 2f );
		shape = new Shape(centerXY, Math.min(bitmapWidth/2, bitmapHeight/2) / 2f);
		
	}

	/*private void changeBitmapFocalDrawerCircle() {

		if (bitmapShapeDrawer != null && imageMatrix != null) {
			float[] matrix = new float[9];
			imageMatrix.getValues(matrix);
			PointF centerXY = shape.centerXY;
			int x = (int) ((centerXY.x - matrix[2]) / matrix[0]);
			int y = (int) ((centerXY.y - matrix[5]) / matrix[4]);
			bitmapShapeDrawer.setCircleAndChangeBitmap(x, y, shape.radius / matrix[0],shape.scaleX,shape.scaleY);
		}
	}*/

	/*public void setBitmapFocalDrawerCircleWithoutChangeBitmap() {
		if (bitmapShapeDrawer != null && imageMatrix != null) {
			float[] matrix = new float[9];
			imageMatrix.getValues(matrix);
			PointF centerXY = shape.centerXY;
			int x = (int) ((centerXY.x - matrix[2]) / matrix[0]);
			int y = (int) ((centerXY.y - matrix[5]) / matrix[4]);
			bitmapShapeDrawer.setCircleWithOutChangeBitmap(x, y, shape.radius / matrix[0]);
		}
	}*/

	/*public boolean storeFocalSizeAndCenterWithZoom(Matrix newImageMatrix) {
		if (newImageMatrix != null) {
			imageMatrix = newImageMatrix;
		}
		if (shape != null) if (bitmapShapeDrawer != null && imageMatrix != null) {
			float[] matrix = new float[9];
			imageMatrix.getValues(matrix);
			PointF focalCenterInBitmap = bitmapShapeDrawer.getFocalCenterXYInOrigSizeBitmap();
			float focalRadiusInBitmap = bitmapShapeDrawer.getFocalRadius();

			shape.setCenterXY(focalCenterInBitmap.x * matrix[0] + matrix[2], focalCenterInBitmap.y * matrix[4] + matrix[5]);
			shape.setRadius(focalRadiusInBitmap * matrix[0]);
			circleTouched = false;
			circleHandeTouched = false;
			// updateFocalDrawerState(false);
			return true;
		}
		return false;

	}*/

	public void drawShape(Canvas canvas) {
		shape.drawShape(canvas);
	}
	

	public boolean touchStart(float x, float y) {
		/*if(bitmapShapeDrawer!=null && bitmapShapeDrawer.tempBitmapsRecycled())
		{
			return false;
		}*/
		if(shape.handeTouched(x, y))
		{
			oldTouchX = x;
			oldTouchY = y;
			return true;
		}
		
		if (shape.isPointInShape(x, y)) {
			circleTouched = true;
			oldTouchX = x;
			oldTouchY = y;
			return true;
		}
		//if (isFocalDrawerActive) 
		{
			if (x >= shape.handeXY.x - shapeSizeHandle.getWidth() / 2 - 5 && x <= shape.handeXY.x + shapeSizeHandle.getWidth() / 2 + 5 && y >= shape.handeXY.y - shapeSizeHandle.getHeight() / 2 - 5 && y <= shape.handeXY.y + shapeSizeHandle.getHeight() / 2 + 5) {
				circleHandeTouched = true;
				oldTouchX = x;
				oldTouchY = y;
				return true;
			}
		}
		return false;
	}
	
	

	public boolean touchMove(float x, float y) {
		
		if(shape.touchedHande!=-1)
		{
			float dx = x - oldTouchX;
			float dy = y - oldTouchY;
			if(shape.moveHandeCircle(dx,dy))
			{
				shape.setHandeXY();
				//changeBitmapFocalDrawerCircle();
				oldTouchX = x;
				oldTouchY = y;
				return true;
			}
			return false;
			
		}
		if (circleTouched) {
			float dx = x - oldTouchX;
			float dy = y - oldTouchY;
			if (Math.abs(dx) >= TOUCH_MOVE_TOLERANCE || Math.abs(dy) > TOUCH_MOVE_TOLERANCE) {
				shape.setCenterXY(shape.centerXY.x + dx, shape.centerXY.y + dy);
				//changeBitmapFocalDrawerCircle();
				oldTouchX = x;
				oldTouchY = y;
			}
			return true;
		} else {
			if (circleHandeTouched) {
				float dx = x - oldTouchX;
				float dy = y - oldTouchY;
				if (Math.abs(dx) >= CIRCLE_HANDE_TOUCH_MOVE_TOLERANCE || Math.abs(dy) > CIRCLE_HANDE_TOUCH_MOVE_TOLERANCE) {
					float absScaleX = Math.abs(shape.scaleX);
					if (dx >= 0 && dy >= 0 ) {
						shape.setRadius((shape.radius*absScaleX + Math.max(dx, dy))/absScaleX);
						//changeBitmapFocalDrawerCircle();
						oldTouchX = x;
						oldTouchY = y;
					} else {
						
						if (dx <= 0 && dy <= 0 &&   Math.min(Math.abs(shape.radius*shape.scaleX)+ Math.min(dx, dy), Math.abs(shape.radius*shape.scaleY)+ Math.min(dx, dy))>=RADIUS_MIN_SIZE) {							
								shape.setRadius((shape.radius*absScaleX+Math.min(dx, dy))/absScaleX);
								//changeBitmapFocalDrawerCircle();
								oldTouchX = x;
								oldTouchY = y;
						}
					}

				}
				return true;
			}
		}
		return false;

	}

	public void touch_up() {
		shape.touchedHande = -1;
		circleTouched = false;
		circleHandeTouched = false;
	}

	public PointF getCircleCenter() {
		if (shape != null) { return shape.centerXY; }
		return null;
	}

	public void onDestroy() {
		if (shapeSizeHandle != null && !shapeSizeHandle.isRecycled()) {
			shapeSizeHandle.recycle();
			shapeSizeHandle = null;
		}
		if(shapeScaleHandeBitmap!=null && !shapeScaleHandeBitmap.isRecycled())
		{
			shapeScaleHandeBitmap.recycle();
			shapeScaleHandeBitmap = null;
		}
	}
	
	public Rect getDrawRect()
	{
		return shape.getDrawRect();
	}
}
